home *** CD-ROM | disk | FTP | other *** search
- // This is a sample drag strip addition. The purpose is to correct the behavior
- // that DS has when an alias of the trash is placed on it.
-
-
- // This demonstrates sending an apple event, looping through mounted volumes,
- // plotting an icon family, ejecting/unmounting volumes, moving items to the
- // trash, and other DragStrip™ addition API features.
-
- // Revisions
-
- // Author Date Comment
- // ------------ ------------- ------------------------------------------
- // JGB MacHack '95 First revision
-
- #include <Palettes.h>
- #include <GestaltEqu.h>
- #include <Icons.h>
- #include <AppleEvents.h>
- #include <A4Stuff.h>
- #include <Files.h>
- #include <Strings.h>
- #include "DS Additions.h"
- #include "Drag.h"
-
- #define ScreenDepth(gdh) ((*((*gdh)->gdPMap))->pixelSize)
-
- pascal long main( DSAdditionParamBlockPtr params)
- {
- long result = 0;
- Rect localRect;
- Point mousePoint;
- OSErr theErr, iErr;
- long iconID ;
- long oldA4 = SetCurrentA4();
- AppleEvent theAppleEvent ;
-
- switch(params->dsMessage)
- {
-
- // -------------------------------------------------------
- // Given an Init or Close message, do what we need to
- // -------------------------------------------------------
-
- case kMsgInitAddition:
- params->dsRefCon = (long)NewHandle(10); //Allocate some memory for some reason
- result = MemError();
- InitAppleEvents();
- break;
-
- case kMsgCloseAddition:
- if(params->dsRefCon != nil)
- {
- DisposeHandle((Handle)params->dsRefCon);
- }
- break;
-
-
- // -------------------------------------------------------
- // Given a draw or hilite message, draw what we need into
- // the provided rectangle
- // -------------------------------------------------------
-
- case kMsgDraw:
- case kMsgDrawHilite:
-
- localRect = params->dsIconRect;
- iconID = GetTrashIcon() ;
- PlotIconID( &localRect ,
- atBottom + atVerticalCenter ,
- ttNone ,
- iconID );
-
- params->dsNextDrawTime = TickCount() + (60 * 3); //Draw again in 3 seconds
-
- break;
-
-
- // -------------------------------------------------------
- // Given a hit message, do whatever we do when we are hit
- // -------------------------------------------------------
-
- case kMsgHit:
-
- localRect = params->dsLocalRect;
- GetMouse( &mousePoint );
-
- // Make sure that the user actually let go inside the rect
- // before doing our thing.
-
- while(StillDown() && PtInRect(mousePoint, &localRect)) {
- GetMouse(&mousePoint);
- }
-
- if( ! StillDown() )
- {
- OSType fndrSig = 'MACS';
- AEAddressDesc target ;
-
- AECreateDesc( typeApplSignature ,
- &fndrSig ,
- sizeof( fndrSig ) ,
- &target );
-
- iErr = AECreateAppleEvent( kAEFinderEvents,
- 'empt',
- &target,
- kAutoGenerateReturnID,
- kAnyTransactionID,
- &theAppleEvent );
-
- iErr = AESend( &theAppleEvent,
- nil,
- kAENoReply + kAECanInteract,
- kAENormalPriority,
- 3600,
- nil,
- nil );
-
- AEDisposeDesc( &target );
- AEDisposeDesc( &theAppleEvent );
- }
-
- break;
-
-
- // -------------------------------------------------------
- // Given a drop message, pull the files out of the
- // DragReference then do what you want with them.
- // -------------------------------------------------------
-
- case kMsgDropOccurred:
- {
- unsigned short items, index, flavors, j ;
- ItemReference theItemRef ;
- FlavorType theType ;
- HFSFlavor flavorData ;
- Size dataSize ;
- unsigned long dataOffset = 0;
-
- CountDragItems( params->dsDragReference, &items );
-
- for (index = 1; index <= items; index++)
- {
- iErr = GetDragItemReferenceNumber( params->dsDragReference,
- index,
- &theItemRef );
- iErr = CountDragItemFlavors( params->dsDragReference,
- theItemRef,
- &flavors );
- for( j = 1 ; j <= flavors ; j++)
- {
- iErr = GetFlavorType( params->dsDragReference,
- theItemRef,
- j,
- &theType );
-
- switch( theType )
- {
- case 'hfs ': // We an HFS Flavor was dropped on us
- // Move this puppy to the trash
-
- iErr = GetFlavorDataSize( params->dsDragReference,
- theItemRef,
- theType,
- &dataSize);
-
- iErr = GetFlavorData( params->dsDragReference,
- theItemRef,
- theType,
- &flavorData,
- &dataSize,
- dataOffset );
-
- TrashItem( flavorData );
-
- break;
-
- }
-
- }
-
- }
- break;
- }
-
- }
-
- SetA4(oldA4);
- return result;
- }
-
-
-
-
- // ------------------------------------------------------------------
- // GetTrashIcon
- //
- // Based on the current state of the trash on all volumes, return the
- // resource ID of the icon to plot.
- // ------------------------------------------------------------------
-
- long GetTrashIcon ( void )
- {
- VolumeParam paramBlock ;
- CInfoPBRec pb ;
- Str255 volName , dirName ;
- OSErr checkErr , theErr ;
- long trashFiles ;
- short i = 1 ;
- short volRefNo , trashVRefNo ;
- long trashDirID ;
- long iconID = -3993 ;
-
- theErr = noErr ;
-
- // Walk through all mounted volumes
- for( i = 1 ; theErr == noErr ; i++)
- {
- paramBlock.ioVolIndex = i ;
- paramBlock.ioNamePtr = volName ;
- paramBlock.ioVRefNum = volRefNo ;
-
- theErr = PBGetVInfo( (ParmBlkPtr) ¶mBlock , FALSE ) ;
-
- volRefNo = paramBlock.ioVRefNum ;
-
- if( theErr == noErr )
- {
- checkErr = FindFolder( volRefNo ,
- kTrashFolderType ,
- kDontCreateFolder ,
- &trashVRefNo ,
- &trashDirID );
-
- pb.dirInfo.ioVRefNum = volRefNo ;
- pb.dirInfo.ioFDirIndex = -1 ;
- pb.dirInfo.ioNamePtr = dirName ;
- pb.dirInfo.ioDrDirID = trashDirID ;
-
- checkErr = PBGetCatInfo( &pb , FALSE );
-
- trashFiles = pb.dirInfo.ioDrNmFls ;
-
- // If the trash folder has any items, return # and break
-
- if( trashFiles > 0 )
- {
- iconID = -3984 ;
- theErr = nsvErr ;
- }
-
- }
-
- }
-
- return iconID ;
- }
-
-
-
- // ------------------------------------------------------------------
- // InitAppleEvents
- //
- // Initialize AppleEvent sender. Beep and return 1 if not supported.
- // ------------------------------------------------------------------
-
- long InitAppleEvents( void )
- {
- long feature, result = 0 ;
- OSErr err ;
-
- err = Gestalt( gestaltAppleEventsAttr, &feature );
-
- if( err != noErr )
- {
- SysBeep( 10 );
- result = 1 ;
- }
-
- return result;
- }
-
-
-
- // ------------------------------------------------------------------
- // TrashItem
- //
- // Send this "thing" to hell!
- // ------------------------------------------------------------------
-
- void TrashItem( HFSFlavor hfsFlavor )
- {
- OSErr result = noErr;
- ParamBlockRec paramBlock ;
- Str255 pathName ;
-
- if((hfsFlavor.fileType == 'disk') && (hfsFlavor.fileCreator == 'MACS')) //Don't unmount the startup volume
- {
-
- if (hfsFlavor.fileSpec.vRefNum != -1) // This is a drive
- {
- short driveNumber;
-
- driveNumber = GetDriveNumber(hfsFlavor.fileSpec.vRefNum);
-
- result = UnmountVol(nil, hfsFlavor.fileSpec.vRefNum);
-
- if(result == noErr)
- {
- result = Eject(nil, driveNumber);
- }
- }
- else {
- result = -50;
- }
- }
- else // We are trashing an actual file or folder
- {
- FSSpec trashFolder;
- FInfo fndrInfo;
- Str63 newName = "\p" ;
- char addName ;
- short strLen , copyIDPos ;
-
- if(result == noErr && MakeSpecialFolderFSSpec(hfsFlavor.fileSpec.vRefNum, &trashFolder, kTrashFolderType))
- {
- result = FSpCatMove( &hfsFlavor.fileSpec , &trashFolder);
- if( result == dupFNErr )
- {
- // there is already an item named this in the trash - how often does this happen anyway?
- short i;
-
- strLen = hfsFlavor.fileSpec.name[0] ;
-
- copyIDPos = strLen + 1 ;
- if( copyIDPos > 62 ) copyIDPos = 62 ;
-
- for (i = 1 ; result == dupFNErr ; i++ )
- {
- addName = (char)(i+(short)'a') ;
- BlockMove( &hfsFlavor.fileSpec.name[1] , &newName[1] , strLen );
- BlockMove( &addName , &newName[copyIDPos] , 1 );
- newName[0] = copyIDPos;
-
- result = FSpRename( &hfsFlavor.fileSpec , newName );
-
- BlockMove( newName , &hfsFlavor.fileSpec.name , copyIDPos + 1 );
-
- result = FSpCatMove( &hfsFlavor.fileSpec , &trashFolder);
- }
- }
- UpdateParentFolderModDate( &hfsFlavor.fileSpec );
- }
- }
- }
-
-
-
-
- // ------------------------------------------------------------------
- // MakeSpecialFolderFSSpec
- //
- // Courtesy of Chris Evans
- // Return a finder folder's FSSpec
- // ------------------------------------------------------------------
-
- Boolean MakeSpecialFolderFSSpec(short vRefNum, FSSpec *folderSpec, OSType folder)
- {
- short folderVRefNum;
- long folderDirID;
- OSErr theErr;
- Boolean result = false;
-
- if(FindFolder(vRefNum, folder, kCreateFolder, &folderVRefNum, &folderDirID) == noErr)
- {
- CInfoPBRec thePB;
- folderSpec->name[0] = 0;
-
- thePB.dirInfo.ioCompletion = 0L;
- thePB.dirInfo.ioNamePtr = (StringPtr) &folderSpec->name;
- thePB.dirInfo.ioVRefNum = folderVRefNum;
- thePB.dirInfo.ioFDirIndex = -1;
- thePB.dirInfo.ioDrDirID = folderDirID;
-
- theErr = PBGetCatInfo(&thePB, false);
- if(theErr == noErr )
- {
- folderSpec->parID = thePB.dirInfo.ioDrParID;
- folderSpec->vRefNum = folderVRefNum;
- result = true;
- }
- }
-
- return result;
- }
-
-
-
- // ------------------------------------------------------------------
- // GetDriveNumber
- //
- // Courtesy of Chris Evans
- // Return a finder folder's FSSpec
- // ------------------------------------------------------------------
-
- short GetDriveNumber( short vRefNum )
- {
- QHdrPtr qhp;
- VCB *vcbp;
-
- qhp = GetVCBQHdr(); // Address of queue header
-
- vcbp = ( VCB *) qhp->qHead;
-
- while( vcbp )
- {
- if( vcbp->vcbVRefNum == vRefNum )
- {
- return vcbp->vcbDrvNum;
- }
- vcbp = (VCB *)vcbp->qLink;
- }
- return -1;
-
- }
-
-
-
- // ------------------------------------------------------------------
- // UpdateFolderModDate
- //
- // Update a folder so the finder redraws it.
- // ------------------------------------------------------------------
-
- void UpdateParentFolderModDate( FSSpec *theSpec )
- {
- CInfoPBRec pb;
- OSErr theErr;
-
- pb.dirInfo.ioCompletion = nil;
- pb.dirInfo.ioNamePtr = nil;
- pb.dirInfo.ioVRefNum = theSpec->vRefNum;
- pb.dirInfo.ioFDirIndex = -1;
- pb.dirInfo.ioDrDirID = theSpec->parID;
-
- theErr = PBGetCatInfo(&pb, false);
- if(theErr == noErr)
- {
- pb.dirInfo.ioDrMdDat = LMGetTime();
- pb.dirInfo.ioDrDirID = theSpec->parID;
- PBSetCatInfo(&pb, false);
- }
- }